#include "../include/mergeToVx.h"
#include "../include/busapi.h"
#include <stdio.h>

#define MY_INSTANCE     (1)
#define MY_CARD_TYPE	(CPCI1553)
#define BC_CHANNEL		(CHANNEL_1)
#define RT_CHANNEL		(CHANNEL_2)

API_BC_MBUF		bc_msg[15];	
API_INT_FIFO	sIntFIFO;	
int	nBCMsgCnt = 0, g_bcChId = 0,g_rtChId = 0;

BT_INT _stdcall Event_handler_Function(BT_UINT cardnum, struct api_int_fifo *pFIFO);

void BCAperiodProc(void)
{
	while(1)
	{		
		while (BusTools_BC_AperiodicTest(g_bcChId, 0) == API_BC_APERIODIC_RUNNING);						
		BusTools_BC_AperiodicRun(g_bcChId, 0, 0, 1, 20);
		taskDelay(1);
	}		
}

void BcAperiodTest(void)
{
	char				c;
	API_BC_MBUF			bc_msg_rc;
    int  				dev_num, mode;
    int					status, i, j;
	unsigned short		cmd, sts;
	API_RT_ABUF			Abuf_RT1;
	API_RT_CBUF			Cbuf_RT1SA1R;	 //RT control buffer structures.
	API_RT_CBUF			Cbuf_RT1SA2T;
	API_RT_MBUF_WRITE	msg_buffer_write;
	API_RT_MBUF_READ	msg_buffer_read;
	
	
	printf("Initializing API with BusTools_API_OpenChannel\n");
	
    // First find the device based on type and instance.
    dev_num = BusTools_FindDevice(MY_CARD_TYPE, MY_INSTANCE);
    if (dev_num < 0)
    {
    	printf("ERROR IN BUSTOOLS_FINDDEVICE.\n");	
    }
	
    // Open the device and get the channel id.
    mode = API_B_MODE | API_SW_INTERRUPT;  // 1553B protocol, use SW interrupts.
    status = BusTools_API_OpenChannel(&g_bcChId, mode, dev_num, BC_CHANNEL);
	
	if (status == API_SUCCESS)
	{
		printf("Success\n");
		
		// Now lets set up a simple BC.
		// Initialize BC for no interrupts, no retries, no resp at 16us, late resp at 14us,
		// minor frame time of 20000us, 1 data buffer per message.
		
		status = BusTools_SetInternalBus(g_bcChId, 0);
		if (status != API_SUCCESS)
		{
			printf("ERROR = %d\n",status);
		}
		
		printf("BC Init\n");
		status = BusTools_BC_Init(g_bcChId, 0, BT1553_INT_END_OF_MESS, 0, 16, 14, 20000, 1);
		if (status != API_SUCCESS)
		{
			printf("ERROR = %d\n",status);	
		}
		
		// Allocate memory on the board for three message blocks.
		printf("MSG Alloc\n");
		status = BusTools_BC_MessageAlloc(g_bcChId, 3);
		if (status != API_SUCCESS)
		{
			 printf("ERROR = %d\n",status);	
		}
		
		// First message (1-T-1-10).
		printf("MSG 0\n");
		memset(&bc_msg[0], 0, sizeof(bc_msg[0]));    // Clear all fields.
		bc_msg[0].messno				= 0;		// Message number
		bc_msg[0].control = BC_CONTROL_MESSAGE;		// This is a standard BC message.
		bc_msg[0].control |= BC_CONTROL_CHANNELA;	// Send message on bus A (primary).
		bc_msg[0].control |= BC_CONTROL_BUFFERA;	// Only using one buffer, buffer A
		bc_msg[0].control |= BC_CONTROL_INTERRUPT;
		bc_msg[0].control |= BC_CONTROL_MFRAME_BEG;
		bc_msg[0].control |= BC_CONTROL_MFRAME_END;
		bc_msg[0].messno_next			= 1;		// Next message number, go to msg #1
		bc_msg[0].mess_command1.rtaddr	= 1;		// Command word 1, RT address
		bc_msg[0].mess_command1.subaddr = 1;		// Command word 1, Subaddress
		bc_msg[0].mess_command1.wcount	= 0;		// Command word 1, word count, 0-31, 0=32 words
		bc_msg[0].mess_command1.tran_rec = 1;		// Command word 1, transmit (1) or receive (0)
		bc_msg[0].gap_time				= 10;		// Intermessage gap time in microseconds
		
		// Fill data buffer
		for (i = 0; i < 32; i++)
		{
			 bc_msg[0].data[0][i] = 0;	
		}		
		// Write the message to board memory
		status = BusTools_BC_MessageWrite(g_bcChId, 0, &bc_msg[0]);
		if (status != API_SUCCESS)
		{
			 printf("ERROR = %d\n",status);	
		}

		printf("MSG 1\n");
		memset(&bc_msg[1], 0, sizeof(bc_msg[1]));   // Clear all fields.
		bc_msg[1].messno				= 1;		// Message number
		bc_msg[1].control = BC_CONTROL_MESSAGE;		// This is a standard BC message.
		bc_msg[1].control |= BC_CONTROL_CHANNELA;	// Send message on bus A (primary).
		bc_msg[1].control |= BC_CONTROL_BUFFERA;	// Only using one buffer, buffer A
		bc_msg[1].control |= BC_CONTROL_INTERRUPT;
		bc_msg[0].control |= BC_CONTROL_MFRAME_BEG;
		bc_msg[0].control |= BC_CONTROL_MFRAME_END;
		bc_msg[1].messno_next			= 0xffff;	// Next message number, go to msg #1
		bc_msg[1].mess_command1.rtaddr	= 1;		// Command word 1, RT address
		bc_msg[1].mess_command1.subaddr = 2;		// Command word 1, Subaddress
		bc_msg[1].mess_command1.wcount	= 0;		// Command word 1, word count, 0-31, 0=32 words
		bc_msg[1].mess_command1.tran_rec = 0;		// Command word 1, transmit (1) or receive (0)
		bc_msg[1].gap_time				= 10;		// Intermessage gap time in microseconds
		
		// Fill data buffer
		for (i = 0; i < 32; i++) 
		{
			bc_msg[1].data[0][i] = 0x2400 + i;	
		}
		
		// Write the message to board memory
		status = BusTools_BC_MessageWrite(g_bcChId, 1, &bc_msg[1]);
		if (status != API_SUCCESS)
		{
			printf("ERROR = %d\n",status);	
		}

		// Setup for our interrupt event handling functions
		memset(&sIntFIFO, 0, sizeof(sIntFIFO));
		sIntFIFO.function       = Event_handler_Function;
		sIntFIFO.iPriority      = THREAD_PRIORITY_BELOW_NORMAL;
		sIntFIFO.dwMilliseconds = INFINITE;
		sIntFIFO.iNotification  = 0;
		
		// Register for BC message events
		sIntFIFO.FilterType     = EVENT_BC_MESSAGE;
		for (i = 0; i < 32; i++)
		{
			for (j = 0; j < 32; j++)
			{
				sIntFIFO.FilterMask[i][0][j] = 0xFFFFFFFF;
				sIntFIFO.FilterMask[i][1][j] = 0xFFFFFFFF;
			}
		}	
		
		// Call the register function to register and start the thread.
		printf("Registering event handler\n");
		status = BusTools_RegisterFunction(g_bcChId, &sIntFIFO, REGISTER_FUNCTION);
		if (status != API_SUCCESS)
		{
			printf("Error = %d.\n", status);
		} 
		else
		{
			 printf("Success.\n");	
		}	

		/*rt config*/
		status = BusTools_API_OpenChannel(&g_rtChId, mode, dev_num, RT_CHANNEL);
		if (status != API_SUCCESS) 
		{
			printf("ERROR = %d\n",status);	
		}
			
		status = BusTools_SetInternalBus(g_rtChId, 0);
		if (status != API_SUCCESS)
		{
			printf("ERROR = %d\n",status);	
		}
			
		BusTools_SetVoltage(g_rtChId, 19800, 0);
		printf("Initializing RT functionality\n");
		status = BusTools_RT_Init(g_rtChId, 0);
		
		if (status == API_SUCCESS)
		{
			printf("Rt Success.\n");
		
			/*Setup RT address buffer for our RT (RT1)*/
			Abuf_RT1.enable_a = 1;			// Respond on bus A
			Abuf_RT1.enable_b = 1;			// Respond on bus B
			Abuf_RT1.inhibit_term_flag = 1;	// Inhibit terminal flag in status word
			Abuf_RT1.status = 0x0800;		// Set status word
			Abuf_RT1.bit_word = 0x0000;		// Set BIT word (for mode code 19)
			status = BusTools_RT_AbufWrite(g_rtChId, 1, &Abuf_RT1);
			if (status != API_SUCCESS) 
			{
				printf("Error %d on BusTools_RT_AbufWrite.\n",status);
			}
					
			/*Setup a control buffer - RT1, SA1, Send, 1 buffer*/
			/*any word count is legal*/
			Cbuf_RT1SA1R.legal_wordcount = 0xFFFFFFFF; 
			status = BusTools_RT_CbufWrite(g_rtChId, 1, 1, 1, 1, &Cbuf_RT1SA1R);
			if (status != API_SUCCESS)
			{
				 printf("Error %d on BusTools_RT_CbufWrite.\n",status);	
			}
				
			/*Setup a control buffer - RT1, SA2, receive, 1 buffer*/
			Cbuf_RT1SA2T.legal_wordcount = 0xFFFFFFFF;  /*any word count is legal*/
			status = BusTools_RT_CbufWrite(g_rtChId, 1, 2, 0, 1, &Cbuf_RT1SA2T);
			if (status != API_SUCCESS)
			{
				 printf("Error %d on BusTools_RT_CbufWrite.\n",status);
			}
				
			/*Put some data in our transmit buffer*/
			msg_buffer_write.enable = 0;		// No interrupts enabled
			msg_buffer_write.error_inj_id = 0;	// No error injection
			
			memset(&msg_buffer_write,0,sizeof(API_RT_MBUF_WRITE));//wy
				
			for (i = 0; i < 32; i++)
			{
				msg_buffer_write.mess_data[i] = 0xEF0 + i;
			}
					
			status = BusTools_RT_MessageWrite(g_rtChId, 1, 1, 1, 0, &msg_buffer_write);
			if (status != API_SUCCESS)
			{
				printf("Error %d on BusTools_RT_MessageWrite.\n",status);
			} 
				
			/*Start the bus controller, will start list at msg #0*/
/*			printf(" Start BC\n");
			status = BusTools_BC_StartStop(g_bcChId, 1);
			if (status != API_SUCCESS)
			{
				printf("ERROR = %d\n",status);
			}*/
				
			/*Now lets turn on our RT */
			printf(" Start RT\n");
			status = BusTools_RT_StartStop(g_rtChId, 1);
			if (status != API_SUCCESS)
			{
				printf("Error %d on BusTools_RT_StartStop.\n",status);
			} 
		}
		
		if(ERROR == taskSpawn("AperiodThread",100,0,10000,(FUNCPTR)BCAperiodProc,0,0,0,0,0,0,0,0,0,0))
		{
			printf("Thread create error!\n");
		}
				
		do
		{
			printf("\nInput Q to stop RT and exit, anything else to read RT1 SA1 RCV data buffer.\n");
			scanf("%c",&c);

			if (c != 'Q') 
			{
				printf("Reading data for RT1 SA1 RCV\n");
				
				status = BusTools_RT_MessageRead(g_rtChId, 1, 2, 0, 0, &msg_buffer_read);
				if (status != API_SUCCESS)
				{
					printf("ERROR READING RT MESSAGE, Error = %d\n",status);
				}
				else 
				{

					printf("RT1 SA1 RCV Data Buffer:\n");
					memcpy(&cmd, &msg_buffer_read.mess_command, sizeof(msg_buffer_read.mess_command));
					printf("Command word = %04X\n",cmd);
					for (i = 0; i < 32; i++)
					{
						printf("%04x ",msg_buffer_read.mess_data[i]);
						if (!((i+1)%8))
						{
							printf("\n");	
						}
					} 
					memcpy(&sts, &msg_buffer_read.mess_status, sizeof(msg_buffer_read.mess_status));
					printf("Status word  = %04X\n",sts);
				}
				
				status = BusTools_BC_MessageRead(g_bcChId, 0, &bc_msg_rc);
				
				//printf("bufferID:%d\n",sIntFIFO->fifo[tail].bufferID);
				if (status == API_SUCCESS) 
				{
					for(i = 0; i < 32; i++)
					{
						printf("%04x ",bc_msg_rc.data[0][i]);
						if (!((i+1)%8))
						{
							printf("\n");	
						}
					}
				}
			}
		} while (c != 'Q'); 
				
		printf("Aperiod message send timer started, input anything to exit.\n");
		scanf("%c", &c);

		taskDelay(10);

		printf("Unregistering BC event handler\n");
		BusTools_RegisterFunction(g_bcChId, &sIntFIFO, UNREGISTER_FUNCTION);

		// We're done.  Close API and board
		printf("Closing API\n");
		status = BusTools_API_Close(g_bcChId);
		if (status == API_SUCCESS)
		{
			printf("Success.\n");
		}
		else
		{
			printf("FAILURE, error = %d\n", status);
		}
		
		printf("BC message count = %d\n", nBCMsgCnt);

	} // End of if (initialization successful)
	else 
	{
		printf("FAILURE, error = %d\n", status);	
	}
	
	printf("FINISHED.\n");
}

BT_INT _stdcall Event_handler_Function(BT_UINT cardnum, struct api_int_fifo *sIntFIFO)
{
	BT_INT				tail;	           // FIFO Tail index
	API_BC_MBUF			bc_msg;
	
	// Loop through all entries in the FIFO
	// Fetch entries from the FIFO: Get the tail pointer and extract the entry
	// it points to.   When (head == tail) then FIFO is empty.
	tail = sIntFIFO->tail_index;
	while ( tail != sIntFIFO->head_index )
	{
		if ( sIntFIFO->fifo[tail].event_type & EVENT_BC_MESSAGE )
		{
			//  Process a BC interrupt:
			//sIntFIFO->fifo[tail].buffer_off       // Byte address of buffer
			//sIntFIFO->fifo[tail].rtaddress        // RT address
			//sIntFIFO->fifo[tail].transrec         // Transmit/Receive
			//sIntFIFO->fifo[tail].subaddress       // Subaddress number
			//sIntFIFO->fifo[tail].wordcount        // Word count
			//sIntFIFO->fifo[tail].bufferID         // BC message number
			
			BusTools_BC_MessageRead(g_bcChId, sIntFIFO->fifo[tail].bufferID, &bc_msg);
			nBCMsgCnt++;	
		}
		// Now update and store the tail pointer.
		tail++;                         // Next entry
		tail &= sIntFIFO->mask_index;   // Wrap the index
		sIntFIFO->tail_index = tail;    // Save the index
	}
	return( API_SUCCESS );
}
	

